package com.af.soldiers.timer;

import com.af.soldiers.config.Monitor;
import com.af.soldiers.job.RunSql;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;

@Component
public class GetJob {

    @Autowired
    private Monitor monitor;

    @Autowired
    private RunSql runSql;

    //标记上此是否执行过
    private static boolean runOver = false;

    HttpComponentsClientHttpRequestFactory httpRequestFactory;

    private static final Logger logger = LoggerFactory.getLogger(GetJob.class);

    public GetJob(){
        httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(1000 * 10);
        httpRequestFactory.setConnectTimeout(1000 * 10);
        httpRequestFactory.setReadTimeout(1000 * 10);
    }

    /**
     * 定时器，获取任务，若领取到任务，就会按照任务要求执行sql
     */
    @Async
    @Scheduled(cron = "0/30 * * * * ? ")
    public void getJob() {
        try {
            logger.info("begin to get Job");
            ResponseEntity<String> forEntity = new RestTemplate(httpRequestFactory).getForEntity(monitor.getBackUrl() + "task/get/" + monitor.getId(), String.class);
            JSONObject res = JSON.parseObject(forEntity.getBody());
            JSONArray data = res.getJSONArray("data");
            if (data.size() > 0 && !runOver){
                logger.info("Job is existence");
                new Thread(()-> {
                    distributor(data);
                }).start();
                runOver = true;
            }else {
                runOver = false;
            }
        } catch (Exception e){
            e.printStackTrace();
            logger.error("获取任务异常:" , e);
        }


    }

    /**
     * 获取到的任务列表循环调用
     * @param data
     */
    public void distributor(JSONArray data){
        for (int i = 0; i < data.size() ; i++) {
            doSql(data.getJSONObject(i));
        }
    }

    /**
     * 根据类型执行sql
     * @param job
     */
    public void doSql(JSONObject job){
            System.out.println("准备执行sql");
            int state = 0;
            String msg = null;
            try {
                if ("select".equals(job.get("taskType").toString())){
                    JSONArray taskSql = runSql.select(job.get("taskSql").toString());
                    if (taskSql.getJSONObject(0).getInteger("num") > 0){
                        sendMSG(job.get("taskName").toString() + "\n" + taskSql.toString());
                    }
                    msg = taskSql.toJSONString();
                }else if ("update".equals(job.get("taskType").toString())){
                    Integer num = runSql.update(job.get("taskSql").toString());
                    if ( num > 0){
                        sendMSG(job.get("taskName").toString() + "\n影响行数" + num);
                    }
                    msg = num.toString();
                }else if("call".equals(job.get("taskType").toString())){
                    String res = runSql.call(job.get("taskSql").toString());
                    if ( ! res.contains("没有需要处理的数据")){
                        sendMSG(job.get("taskName").toString() + "\n执行结果：" + res);
                    }
                    msg = res;
                }else {
                    throw new RuntimeException("执行任务的类型错误");
                }
                state = 1;
            } catch (Exception throwable) {
                System.out.println("in Error");
                sendMSG("任务ID：" + job.get("id") + "执行出错\n  错误信息：" + throwable.getMessage());
                msg = "错误信息：" + throwable.getMessage();
                throwable.printStackTrace();
            } finally {
                System.out.println("in finally");
                if (!job.getBooleanValue("runNow")){
                    overJob(job.get("id").toString());
                }
                pushResult(job,msg,state);
                logger.info(job.get("id").toString() + "==> " + msg);
                System.out.println("over finally");
            }

    }

    /**
     * 推送到对应钉钉群内
     * @param msg
     */
    public void sendMSG(String msg){
        JSONObject text = new JSONObject();
        text.put("text",msg);
        text.put("title","通知：");

        JSONObject at = new JSONObject();
        at.put("atMobiles", new ArrayList<>());
        at.put("isAtAll",true);

        JSONObject send = new JSONObject();
        send.put("msgtype","markdown");
        send.put("markdown",text);
        send.put("at",at);
        new RestTemplate().postForEntity(monitor.getBackUrl()+"receive/forward/" + monitor.getId(), send, String.class);
    }


    /**
     * 返回任务执行成功的请求
     * @param id
     */
    public void overJob(String id){
        new RestTemplate().postForEntity(monitor.getBackUrl()+"task/over/" + id, new JSONObject(), String.class);
    }

    /**
     * 将运行结果返回给后台存储
     * @param job
     * @param msg
     * @param state
     */
    public void pushResult(JSONObject job ,String msg,int state){
        JSONObject push = new JSONObject();
        push.put("taskId",Integer.valueOf(job.get("id").toString()));
        push.put("runResult",state);
        push.put("runInformation",msg);
        push.put("runSql",job.get("taskSql").toString());
        if (!job.getBooleanValue("runNow")){
            push.put("runTime",job.get("taskRunTime").toString());
        }else {
            push.put("runTime", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()));
        }

        System.out.println(push);
        new RestTemplate().postForEntity(monitor.getBackUrl()+"taskResult/push", push, JSONObject.class);
    }

}
